package com.yss.sofa.report.engine.util;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.apache.commons.lang3.StringUtils;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;

import com.yss.sofa.report.engine.DataSetData;
import com.yss.sofa.report.engine.Report;

/**
 * 报表数据导出到xml文件
 * @author wangyh
 * @version 2.6.X
 * @since 2.6.X
 */
public final class XmlUtil {
	private static final Logger LOGGER=LoggerFactory.getLogger(XmlUtil.class);
	private XmlUtil() {
	}

	/**
	 * 将report对象转换为xml文件,直接带文件名.
	 * @param report  report对象
	 * @param filename   文件名(可包含路径)
	 * @throws Exception
	 */
	public static void export(Report report, String filename) throws Exception {
		FileOutputStream out = new FileOutputStream(new File(filename));
		try {
			export(report, out);
			out.flush();
		} finally {
			if (out != null) {
				out.close();
			}
		}
	}

	/**
	 * 将report对象转换为pdf字节导出到指定输出流中.(支持多张报表合并输出)
	 * @param report  report对象
	 * @param out  输出流
	 * @throws Exception
	 */
	public static void export(Report report, OutputStream out) throws Exception {
		Map<String, DataSetData> datas = report.getDatas();
		Map<String, Serializable> params = report.getParams();

		Document document = DocumentHelper.createDocument();
		XmlUtil xmlUtil = new XmlUtil();
		// XmlNode xmlNode = xmlUtil.generateXmlNodes();
		xmlUtil.load(report);

		XmlNode xmlNode = xmlUtil.getHeadNode();
		if (xmlNode != null) {
			Element rootElement = document.addElement(xmlNode.getNodeName());
			List<XmlNode> subNodes = xmlNode.getSubNodes();
			List<CustomAttribute> customAttributes = xmlNode.getCustomAttributes();
			if (customAttributes != null) {
				if (customAttributes != null) {
					for (CustomAttribute customAttribute : customAttributes) {
						String attributeName = customAttribute.getAttributeName();
						String attributeValue = StringUtils.defaultString(customAttribute.getAttributeValue());
						rootElement.addAttribute(attributeName, attributeValue);
					}
				}
			}
			for (XmlNode subNode : subNodes) {
				addElementNode(rootElement, subNode, xmlNode.getTemplateAttribute().getPair().get(EAttributeParameters.dataset), null, datas, params);
			}
		} else {
			Element rootElement = document.addElement("root");
			rootElement.setText(" there is nothing !");
		}
		OutputFormat xmlFormat = OutputFormat.createPrettyPrint();
		xmlFormat.setEncoding(xmlUtil.getEncoding());
		xmlFormat.setNewLineAfterDeclaration(false);
		XMLWriter xmlWriter = new XMLWriter(out, xmlFormat);
		xmlWriter.write(document);
		xmlWriter.flush();
		xmlWriter.close();
	}

	private static String getObjectIgnoreCase(Map<String, String> map, String key) {
		for (String k : map.keySet()) {
			if (k.equalsIgnoreCase(key)) {
				return map.get(k);
			}
		}
		return null;
	}

	/**
	 * 递归增加元素
	 * @param parentElement 上级节点
	 * @param subNode 子节点
	 * @param parentDataSetCode 父节点数据集代码
	 * @param parentRecord 父节点记录
	 * @param datas 记录集
	 */
	private static void addElementNode(Element parentElement, XmlNode subNode, String parentDataSetCode, Map<String, String> parentRecord, Map<String, DataSetData> datas,
			Map<String, Serializable> params) {
		String dataSetCode = subNode.getTemplateAttribute().getPair().get(EAttributeParameters.dataset);
		if (StringUtils.isEmpty(dataSetCode)) {
			dataSetCode = parentDataSetCode;
		}
		String subNodeName = subNode.getNodeName();

		if (StringUtils.isNotEmpty(dataSetCode)) {
			DataSetData data = datas.get(dataSetCode);
			if (data == null) {
				LOGGER.warn("add subNode "+subNodeName+", no data set "+dataSetCode+" was found.");
				//parentElement.setText(" there is nothing !");
				return;
			} else {
				List<Map<String, String>> records = data.getRecords();
				if (records == null || records.size() == 0) {
					LOGGER.warn("add subNode "+subNodeName+", data set "+dataSetCode+" records is empty.");
					//parentElement.setText(" there is nothing !");
					return;
				} else {
					/** 循环节点处理 */
					if (subNode.getTemplateAttribute().getNodeType() == ENodeType.loop) {
						for (Map<String, String> rowRecord : records) {
							Element subElement = null;
							if (StringUtils.isNotEmpty(parentDataSetCode) && !dataSetCode.equals(parentDataSetCode)) {
								for (Map.Entry<String, String> entry : rowRecord.entrySet()) {
									String key = entry.getKey();
									String value = entry.getValue();
									if (key.equalsIgnoreCase(subNode.getTemplateAttribute().getPair().get(EAttributeParameters.relationField))) {
										String parentRelationField = subNode.getTemplateAttribute().getPair().get(EAttributeParameters.parentRelationField);
										String parentRecordValue = getObjectIgnoreCase(parentRecord, parentRelationField);
										if (parentRecordValue != null && parentRecordValue.equals(value)) {
											if (StringUtils.isNotEmpty(subNode.getTemplateAttribute().getPair().get(EAttributeParameters.filterField))
													&& StringUtils.isNotEmpty(subNode.getTemplateAttribute().getPair().get(EAttributeParameters.filterFieldValue))) {
												if (key.equalsIgnoreCase(subNode.getTemplateAttribute().getPair().get(EAttributeParameters.filterField))
														&& subNode.getTemplateAttribute().getPair().get(EAttributeParameters.filterFieldValue).equals(value)) {
													subElement = parentElement.addElement(subNodeName);
													break;
												}
											} else {
												subElement = parentElement.addElement(subNodeName);
												break;
											}
										}
									}
								}
							} else {
								if (StringUtils.isNotEmpty(subNode.getTemplateAttribute().getPair().get(EAttributeParameters.filterField))
										&& StringUtils.isNotEmpty(subNode.getTemplateAttribute().getPair().get(EAttributeParameters.filterFieldValue))) {
									for (Map.Entry<String, String> entry : rowRecord.entrySet()) {
										String key = entry.getKey();
										String value = entry.getValue();
										if (key.equalsIgnoreCase(subNode.getTemplateAttribute().getPair().get(EAttributeParameters.filterField))
												&& subNode.getTemplateAttribute().getPair().get(EAttributeParameters.filterFieldValue).equals(value)) {
											subElement = parentElement.addElement(subNodeName);
											break;
										}
									}
								} else {
									subElement = parentElement.addElement(subNodeName);
								}
							}
							if (subElement != null) {
								List<CustomAttribute> customAttributes = subNode.getCustomAttributes();
								if (customAttributes != null) {
									if (customAttributes != null) {
										for (CustomAttribute customAttribute : customAttributes) {
											String attributeName = customAttribute.getAttributeName();
											String attributeValue = StringUtils.defaultString(customAttribute.getAttributeValue());
											if (attributeValue.startsWith(EXmlSymbol.commentSign.getSymbol())) {
												String attributeField = attributeValue.substring(1);
												for (Map.Entry<String, String> entry : rowRecord.entrySet()) {
													String key = entry.getKey();
													String value = entry.getValue();
													if (key.equalsIgnoreCase(attributeField)) {
														subElement.addAttribute(attributeName, value);
														break;
													}
												}
											} else if (attributeValue.startsWith(EXmlSymbol.currencySign.getSymbol())) {
												String attributeField = attributeValue.substring(1);
												attributeValue = (String) params.get(attributeField);
												subElement.addAttribute(attributeName, attributeValue);
											} else {
												subElement.addAttribute(attributeName, attributeValue);
											}
										}
									}
								}
								List<XmlNode> grandSonNodes = subNode.getSubNodes();
								for (XmlNode grandSonNode : grandSonNodes) {
									String grandSonDataSetCode = grandSonNode.getTemplateAttribute().getPair().get(EAttributeParameters.dataset);
									if (StringUtils.isEmpty(grandSonDataSetCode)) {
										grandSonDataSetCode = dataSetCode;
									}
									if (grandSonNode.getTemplateAttribute().getNodeType() == ENodeType.loop) {
										addElementNode(subElement, grandSonNode, dataSetCode, rowRecord, datas, params);
									} else if (grandSonNode.getTemplateAttribute().getNodeType() == ENodeType.leaf) {
										addLeafNode(grandSonNode, subElement, rowRecord, params);
									} else if (grandSonNode.getTemplateAttribute().getNodeType() == ENodeType.fix) {
										addFixNode(grandSonNode, subElement, rowRecord, params);
									} else if (grandSonNode.getTemplateAttribute().getNodeType() == ENodeType.fixAll) {
										addFixAllNode(grandSonNode, subElement, rowRecord, params);
									}
								}
							}
						}
						return;
					} else if (subNode.getTemplateAttribute().getNodeType() == ENodeType.fix) {
						/** 外层固定节点处理 */
						Map<String, String> rowRecord = new HashMap<String, String>();
						if (records != null) {
							rowRecord = records.get(0);
						}
						addFixNode(subNode, parentElement, rowRecord, params);
					} else if (subNode.getTemplateAttribute().getNodeType() == ENodeType.fixAll) {
						/** 外层固定节点处理 */
						Map<String, String> rowRecord = new HashMap<String, String>();
						if (records != null) {
							rowRecord = records.get(0);
						}
						addFixAllNode(subNode, parentElement, rowRecord, params);
					} else if (subNode.getTemplateAttribute().getNodeType() == ENodeType.leaf) {
						/** 外层叶子节点处理 */
						Map<String, String> rowRecord = new HashMap<String, String>();
						if (records != null) {
							rowRecord = records.get(0);
						}
						addLeafNode(subNode, parentElement, rowRecord, params);
					}
					return;
				}
			}
		} else if (subNode.getTemplateAttribute().getNodeType() == ENodeType.fix) {
			/** 外层固定节点处理 */
			Map<String, String> rowRecord = new HashMap<String, String>();
			addFixNode(subNode, parentElement, rowRecord, params);
		} else if (subNode.getTemplateAttribute().getNodeType() == ENodeType.fixAll) {
			/** 外层固定节点处理 */
			Map<String, String> rowRecord = new HashMap<String, String>();
			addFixAllNode(subNode, parentElement, rowRecord, params);
		} else if (subNode.getTemplateAttribute().getNodeType() == ENodeType.leaf) {
			/** 外层叶子节点处理 */
			Map<String, String> rowRecord = new HashMap<String, String>();
			addLeafNode(subNode, parentElement, rowRecord, params);
		}else {
			LOGGER.warn(parentElement.getName() +"add subNode "+subNode+" is empty.");
			//parentElement.setText(" there is nothing !");
			return;
		}
	}

	private static void addFixNode(XmlNode grandSonNode, Element subElement, Map<String, String> rowRecord, Map<String, Serializable> params) {
		String grandSonNodeName = grandSonNode.getNodeName();
		Element grandSonElement = subElement.addElement(grandSonNodeName);
		grandSonElement.setText(StringUtils.defaultString(grandSonNode.getContent()));
		List<CustomAttribute> customAttributes = grandSonNode.getCustomAttributes();
		if (customAttributes != null) {
			for (CustomAttribute customAttribute : customAttributes) {
				String attributeName = customAttribute.getAttributeName();
				String attributeValue = StringUtils.defaultString(customAttribute.getAttributeValue());
				if (attributeValue.startsWith(EXmlSymbol.commentSign.getSymbol())) {
					String attributeField = attributeValue.substring(1);
					for (Map.Entry<String, String> entry : rowRecord.entrySet()) {
						String key = entry.getKey();
						String value = entry.getValue();
						if (key.equalsIgnoreCase(attributeField)) {
							grandSonElement.addAttribute(attributeName, value);
							break;
						}
					}
				} else if (attributeValue.startsWith(EXmlSymbol.currencySign.getSymbol())) {
					String attributeField = attributeValue.substring(1);
					attributeValue = (String) params.get(attributeField);
					grandSonElement.addAttribute(attributeName, attributeValue);
				} else {
					grandSonElement.addAttribute(attributeName, attributeValue);
				}
			}
		}
	}

	private static void addFixAllNode(XmlNode grandSonNode, Element subElement, Map<String, String> rowRecord, Map<String, Serializable> params) {
		String grandSonNodeName = grandSonNode.getNodeName();
		Element grandSonElement = subElement.addElement(grandSonNodeName);
		grandSonElement.setText(StringUtils.defaultString(grandSonNode.getContent()));
		List<CustomAttribute> customAttributes = grandSonNode.getCustomAttributes();
		if (customAttributes != null) {
			for (CustomAttribute customAttribute : customAttributes) {
				String attributeName = customAttribute.getAttributeName();
				String attributeValue = StringUtils.defaultString(customAttribute.getAttributeValue());
				grandSonElement.addAttribute(attributeName, attributeValue);
			}
		}
	}

	private static void addLeafNode(XmlNode grandSonNode, Element subElement, Map<String, String> rowRecord, Map<String, Serializable> params) {
		String field = grandSonNode.getTemplateAttribute().getPair().get(EAttributeParameters.field);
		String grandSonNodeName = grandSonNode.getNodeName();
		if (StringUtils.isEmpty(field)) {
			field = grandSonNodeName;
		}
		Element grandSonElement = null;
		if (field.startsWith(EXmlSymbol.currencySign.getSymbol())) {
			String attributeField = field.substring(1);
			grandSonElement = subElement.addElement(grandSonNodeName);
			grandSonElement.setText(StringUtils.defaultString((String) params.get(attributeField)));
		} else {
			for (Map.Entry<String, String> entry : rowRecord.entrySet()) {
				String key = entry.getKey();
				String value = entry.getValue();

				if (key.equalsIgnoreCase(field)) {
					grandSonElement = subElement.addElement(grandSonNodeName);
					grandSonElement.setText(StringUtils.defaultString(value));
					break;
				}
			}
		}
		if (grandSonElement != null) {
			List<CustomAttribute> customAttributes = grandSonNode.getCustomAttributes();
			if (customAttributes != null) {
				for (CustomAttribute customAttribute : customAttributes) {
					String attributeName = customAttribute.getAttributeName();
					String attributeValue = StringUtils.defaultString(customAttribute.getAttributeValue());
					if (attributeValue.startsWith(EXmlSymbol.commentSign.getSymbol())) {
						String attributeField = attributeValue.substring(1);
						for (Map.Entry<String, String> entry2 : rowRecord.entrySet()) {
							String key2 = entry2.getKey();
							String value2 = entry2.getValue();
							if (key2.equalsIgnoreCase(attributeField)) {
								grandSonElement.addAttribute(attributeName, value2);
								break;
							}
						}
					} else if (attributeValue.startsWith(EXmlSymbol.currencySign.getSymbol())) {
						String attributeField = attributeValue.substring(1);
						attributeValue = (String) params.get(attributeField);
						grandSonElement.addAttribute(attributeName, attributeValue);
					} else {
						grandSonElement.addAttribute(attributeName, attributeValue);
					}
				}
			}
		}
	}

	private XmlNode generateXmlNodes() {
		XmlNode grandSonNode2_son = new XmlNode();
		grandSonNode2_son.setNodeName("name");
		TemplateAttribute templateAttribute = new TemplateAttribute();
		templateAttribute.setNodeType(ENodeType.leaf);
		templateAttribute.getPair().put(EAttributeParameters.field, "fname");
		grandSonNode2_son.setTemplateAttribute(templateAttribute);

		XmlNode grandSonNode2_son2 = new XmlNode();
		grandSonNode2_son2.setNodeName("fy");
		templateAttribute = new TemplateAttribute();
		templateAttribute.setNodeType(ENodeType.leaf);
		templateAttribute.getPair().put(EAttributeParameters.field, "fy");
		grandSonNode2_son2.setTemplateAttribute(templateAttribute);

		XmlNode grandSonNode2 = new XmlNode();
		grandSonNode2.setNodeName("student");
		templateAttribute = new TemplateAttribute();
		templateAttribute.setNodeType(ENodeType.loop);
		templateAttribute.getPair().put(EAttributeParameters.dataset, "grades");
		templateAttribute.getPair().put(EAttributeParameters.relationField, "fclass");
		templateAttribute.getPair().put(EAttributeParameters.parentRelationField, "name");
		grandSonNode2.setTemplateAttribute(templateAttribute);
		grandSonNode2.getSubNodes().add(grandSonNode2_son);
		grandSonNode2.getSubNodes().add(grandSonNode2_son2);

		XmlNode grandSonNode = new XmlNode();
		templateAttribute = new TemplateAttribute();
		templateAttribute.getPair().put(EAttributeParameters.field, "name");
		templateAttribute.setNodeType(ENodeType.leaf);
		grandSonNode.setNodeName("className");
		grandSonNode.setTemplateAttribute(templateAttribute);

		XmlNode xmlNode = new XmlNode();
		xmlNode.setNodeName("class");

		templateAttribute = new TemplateAttribute();
		templateAttribute.setNodeType(ENodeType.loop);
		templateAttribute.getPair().put(EAttributeParameters.dataset, "classes");
		templateAttribute.getPair().put(EAttributeParameters.filterField, "name");
		templateAttribute.getPair().put(EAttributeParameters.filterFieldValue, "204班");
		xmlNode.setTemplateAttribute(templateAttribute);
		xmlNode.getSubNodes().add(grandSonNode);
		xmlNode.getSubNodes().add(grandSonNode2);

		XmlNode xmlRootNode = new XmlNode();
		xmlRootNode.setNodeName("students");
		xmlRootNode.getSubNodes().add(xmlNode);
		return xmlRootNode;

	}

	/**
	 * 测试代码
	 * @param args
	 */
	public static void main(String args[]) {
		XmlUtil xmlUtil = new XmlUtil();
		xmlUtil.load(null);
	}

	/**
	 * 装载模板
	 */
	private void load(Report report) {
		try {
			// String filePath = "X:\\report\\student2.xml";
			SAXParserFactory factory = SAXParserFactory.newInstance();
			SAXParser sp = factory.newSAXParser();
			XMLReader reader = sp.getXMLReader();
			reader.setContentHandler(new XmlTemplateHandler());
			// reader.parse(filePath);
			byte content[] = null;
			if(null !=report.getCustomTemplate()){
				 content = report.getCustomTemplate().getTemplateContent();
			}
			if (content != null && content.length > 0) {
				parseXmlDeclarationHeader(new String(content));
				reader.parse(new InputSource(new ByteArrayInputStream(content)));
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	enum EAttributeParameters {
		nodeType, dataset, filterField, filterFieldValue, field, relationField, parentRelationField, unknown
	}

	enum ENodeType {
		loop, leaf, fix, fixAll, unknown
	}

	enum EXmlSymbol {

		commentSign("#"), currencySign("$"), equalSign("="), semicolon(";");

		private String symbol;

		EXmlSymbol(String symbol) {
			this.symbol = symbol;
		}

		public String getSymbol() {
			return symbol;
		}

	}

	/**
	 * 模板属性
	 * @author wangyh
	 */
	class TemplateAttribute {
		/** 配置属性 */
		private Map<EAttributeParameters, String> pair = new HashMap<EAttributeParameters, String>();
		/** 节点类型  */
		private ENodeType nodeType;

		public ENodeType getNodeType() {
			return nodeType;
		}

		public Map<EAttributeParameters, String> getPair() {
			return pair;
		}

		public void setPair(Map<EAttributeParameters, String> pair) {
			this.pair = pair;
		}

		public void setNodeType(ENodeType nodeType) {
			this.nodeType = nodeType;
		}

	}

	/**
	 * 自定义属性
	 * @author wangyh
	 */
	class CustomAttribute {
		/** 属性名 */
		private String attributeName;
		/** 属性值 */
		private String attributeValue;

		public String getAttributeName() {
			return attributeName;
		}

		public void setAttributeName(String attributeName) {
			this.attributeName = attributeName;
		}

		public String getAttributeValue() {
			return attributeValue;
		}

		public void setAttributeValue(String attributeValue) {
			this.attributeValue = attributeValue;
		}
	}

	/**
	 * 节点
	 * @author wangyh
	 */
	class XmlNode {
		/** 节点名称 */
		private String nodeName;
		/** 节点内容  */
		private String content;
		/** 自定义属性 */
		private List<CustomAttribute> customAttributes = new ArrayList<CustomAttribute>();
		/** 模板属性 */
		private TemplateAttribute templateAttribute;
		/** 子节点 */
		private List<XmlNode> subNodes = new ArrayList<XmlNode>();

		public String getNodeName() {
			return nodeName;
		}

		public void setNodeName(String nodeName) {
			this.nodeName = nodeName;
		}

		public List<XmlNode> getSubNodes() {
			return subNodes;
		}

		public void setSubNodes(List<XmlNode> subNodes) {
			this.subNodes = subNodes;
		}

		public List<CustomAttribute> getCustomAttributes() {
			return customAttributes;
		}

		public void setCustomAttributes(List<CustomAttribute> customAttributes) {
			this.customAttributes = customAttributes;
		}

		public TemplateAttribute getTemplateAttribute() {
			return templateAttribute;
		}

		public void setTemplateAttribute(TemplateAttribute templateAttribute) {
			this.templateAttribute = templateAttribute;
		}

		public String getContent() {
			return content;
		}

		public void setContent(String content) {
			this.content = content;
		}

	}

	/** xml层级 */
	private int level = -1;
	/** xml元素结束标识 */
	private boolean isEnd = false;
	/** 头节点 */
	private XmlNode headNode;
	/** 当前节点 */
	private XmlNode currentNode;
	/** 当前层级节点 */
	private Map<Integer, XmlNode> currLevelNodes = new HashMap<Integer, XmlNode>();
	/** xml编码 */
	private String encoding;

	/** xml解析处理器 */
	class XmlTemplateHandler extends DefaultHandler {

		/** 模板标签 */
		private static final String SOFA_REPORT_EXPORT_SETTING = "sofa_report_export_setting";

		@Override
		public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
			level++;
			currentNode = new XmlNode();
			if (level == 0) {
				headNode = currentNode;
			} else if (level > 0) {
				XmlNode parentNode = currLevelNodes.get(level - 1);
				parentNode.getSubNodes().add(currentNode);
			}
			currentNode.setNodeName(qName);
			for (int i = 0; atts != null && i < atts.getLength(); i++) {
				String attName = atts.getQName(i);
				String attValueString = atts.getValue(i);

				TemplateAttribute templateAttribute = new TemplateAttribute();
				if (SOFA_REPORT_EXPORT_SETTING.equalsIgnoreCase(attName)) {
					String settings[] = attValueString.split(EXmlSymbol.semicolon.getSymbol());
					for (String str : settings) {
						String arr[] = str.split(EXmlSymbol.equalSign.getSymbol());
						if (arr != null && arr.length > 1) {
							String key = arr[0];
							String value = arr[1];
							EAttributeParameters eAttributeParameters;
							try {
								eAttributeParameters = EAttributeParameters.valueOf(key);
							} catch (Exception e) {
								eAttributeParameters = EAttributeParameters.unknown;
							}
							if (eAttributeParameters == EAttributeParameters.nodeType) {
								ENodeType nodeType;
								try {
									nodeType = ENodeType.valueOf(value);
								} catch (Exception e) {
									nodeType = ENodeType.unknown;
								}
								templateAttribute.setNodeType(nodeType);
							} else {
								templateAttribute.getPair().put(eAttributeParameters, value);
							}
						}
					}
					currentNode.setTemplateAttribute(templateAttribute);
				} else {
					CustomAttribute customAttribute = new CustomAttribute();
					customAttribute.setAttributeName(attName);
					customAttribute.setAttributeValue(attValueString);
					currentNode.getCustomAttributes().add(customAttribute);
				}
			}
			currLevelNodes.put(level, currentNode);
			isEnd = false;
		}

		@Override
		public void endElement(String uri, String localName, String qName) throws SAXException {
			currLevelNodes.remove(level);
			level--;
			isEnd = true;
		}

		@Override
		public void characters(char[] ch, int start, int length) throws SAXException {
			String content = new String(ch, start, length);
			if (!isEnd) {
				currentNode.setContent(content);
			}
		}
	}

	public XmlNode getHeadNode() {
		return headNode;
	}

	public void setHeadNode(XmlNode headNode) {
		this.headNode = headNode;
	}

	public String getEncoding() {
		return encoding;
	}

	public void setEncoding(String encoding) {
		this.encoding = encoding;
	}

	/**
	 * 解析xml声明头
	 */
	private void parseXmlDeclarationHeader(String xmlContent) {
		int headerPosition = xmlContent.indexOf("?>");
		encoding = "UTF-8";
		if (headerPosition > 0) {
			String headerContent = xmlContent.substring(0, headerPosition);
			int encodingPosition = headerContent.indexOf("encoding");
			if (encodingPosition > 0) {
				String encodingContent = headerContent.substring(encodingPosition);
				int firstDoubleQuotationPosition = encodingContent.indexOf("\"");
				if (firstDoubleQuotationPosition > 0) {
					String firstDoubleQuotationContent = encodingContent.substring(firstDoubleQuotationPosition + 1);
					int secondDoubleQuotationPosition = firstDoubleQuotationContent.indexOf("\"");
					encoding = firstDoubleQuotationContent.substring(0, secondDoubleQuotationPosition);
				}
			}
		}
	}

}
